Blog with Emacs and Pelican - even better !
Fixing some stuff, I decided to look again at how to get a better and easier process to post on my site.
I was already using Org mode with Pelican as seen in Part 1.
But I had to type a few weird things like `{{{dt(….)}}`, which would call a macro, manually (oh no!) enter the date, the properties and then go in the shell `make html` etc …
In the end it was pretty easy to get better … once I found out the org_reader Pelican plugin
1 Install the plugin
Easy ! Go in the folder where I run Pelican from and run :
git clone --recursive https://github.com/getpelican/pelican-plugins
2 Then configure Pelican
Which is quite simple too
PATH="org/blog" PLUGIN_PATHS = ['pelican-plugins'] PLUGINS = ['org_reader'] ORG_READER_EMACS_LOCATION="/usr/local/bin/emacs" ORG_READER_EMACS_SETTINGS="blog-export.el"
3 A bit more delicate: configure Emacs
It was working with my current Emacs setup, but it was also doing a bunch of things adding time to the pages rendering.
The parts I struggled with were having colors in the source blocks and not using inline CSS.
3.1 Source blocks colors
I wanted to keep solarized dark but it wasn't coloring. After looking around it seems it was because it was running from the terminal so not using all the colors.
The fix would be to install Emacs solarized theme and set it to work in the terminal. To do that, clone it and add it to the config, it looks like this:
;; Theme stuff (add-to-list 'custom-theme-load-path (expand-file-name "~/.emacs.d/emacs-color-theme-solarized")) (set-frame-parameter nil 'background-mode 'dark) (set-terminal-parameter nil 'background-mode 'dark) (load-theme 'solarized t)
3.2 Don't inline the CSS
Then it kept trying to set it's own style inline, overriding all the beautifullness `M-x org-html-htmlize-generate-css` puts in a css, used in the pelican theme. It is just a variable to set, for safety I set two since I'm not sure what is used when:
(setq org-html-htmlize-output-type 'css) (setq htmlize-output-type 'css)
3.3 The rest and the full config
Here is the file blog-export.el I use.
The "Org stuff" came mostly from my previous config when I exported HTML from Emacs.
The "Random Stuff" part, I'm not sure it's needed, but since it works, I didn't look too much into it.
;; -*- MODE: emacs-lisp -*- (add-to-list 'load-path (expand-file-name "~/.emacs.d/addons")) (add-to-list 'load-path (expand-file-name "~/.emacs.d/markdown-mode")) ;; Theme stuff (add-to-list 'custom-theme-load-path (expand-file-name "~/.emacs.d/emacs-color-theme-solarized")) (set-frame-parameter nil 'background-mode 'dark) (set-terminal-parameter nil 'background-mode 'dark) (load-theme 'solarized t) (require 'htmlize) (require 'ox) (require 'highlight-indentation) ;; Org stuff (setq org-html-htmlize-output-type 'css) (setq htmlize-output-type 'css) (setq org-export-headline-levels 4 org-html-preamble nil org-export-with-tags t org-export-with-todo-keywords nil org-html-doctype "html5" org-html-html5-fancy t org-export-creator-string nil org-html-postamble nil org-export-with-timestamp nil) (setq org-src-fontify-natively t) (setq org-use-sub-superscripts nil) (setq org-export-with-sub-superscripts nil) (add-to-list 'org-babel-load-languages '(php . t)) (org-babel-do-load-languages 'org-babel-load-languages org-babel-load-languages) ;; Random stuff, not sure if it's needed (add-to-list 'load-path "~/.emacs.d/jade-mode") (require 'ob-php) (require 'web-mode) (require 'sws-mode) (require 'php-mode) (require 'yaml-mode) (require 'jade-mode) (autoload 'markdown-mode "markdown-mode" "Major mode for editing Markdown files" t) (setq tab-always-indent t) (setq tab-width 4) (setq-default indent-tabs-mode nil)
4 Creating a new post
For this, I added an org-mode capture template, so I can do one of the following to move some of my notes to a new Org file ready to post:
- `M-x org-capture`
- `:org-capture`
- `C-c c`
The template :
(setq org-capture-templates '(("b" "Blog" plain (file (capture-report-data-file "~/Sync/org/blog/posts")) "#+DATE: %t \n#+CATEGORY: %^G\n#+TITLE: %?\n") ))
I also had to add a function to generate the path and filename depending on the section I wanted to create the post.
Function capture-report-data-file based on this stack overflow question:
(defun capture-report-data-file (path) (let ((category (completing-read "S(ysadmin)|P(rojects)|M(isc) ? " '("Sysadmin" "Projects" "Misc") nil t)) (title (read-string "Title: ")) ) (expand-file-name (format "%s.org" title) (concat path "/" category))))
The completing-read takes those arguments:
- "S(ysadmin)|P(rojects)|M(isc) ?": it's the prompt
- '("Sysadmin" "Projects" "Misc"): Those are my Pelican categories which are just sub folders in my org/blog folder.
- nil: I don't care :)
- t: set to true to force the choice to only what is offered (here Sysadmin Projects or Misc)
5 Rendering everything and publishing
Standard Pelican procedure:
make html make serve # to check everything is fine make rsync_upload # or any other favourite publishing option